<template>
  <div>
    <h2>大文件分片上传</h2>
    <input type="file" name="" id=""  />
  </div>
</template>

<script>
// 参考地址：https://juejin.cn/post/7074534222748188685#heading-1
import SparkMD5 from 'spark-md5'
import { uploadFile, mergeChunks } from '@/api/org'
export default {
  name: 'BigFileUpload',
  data () {
    return {
      DefualtChunkSize: 5 * 1024 * 1024, // 默认分片的大小
      fileChunkList: [],
      currFile: null
    }
  },
  methods: {
    // 获取文件分块
    getFileChunk (file, chunkSize = this.DefualtChunkSize) {
      return new Promise((resolve) => {
        // 兼容的方式获取文件的slice方法
        const blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
        // 计算需要分多少片
        const chunks = Math.ceil(file.size / chunkSize)
        let currentChunk = 0
        // 追加数组缓冲区
        const spark = new SparkMD5.ArrayBuffer()
        const fileReader = new FileReader()

        fileReader.onload = function (e) {
          console.log('read chunk nr', currentChunk + 1, 'of')

          const chunk = e.target.result
          spark.append(chunk)
          currentChunk++

          if (currentChunk < chunks) {
            loadNext()
          } else {
            const fileHash = spark.end()
            console.info('finished computed hash', fileHash)
            resolve({ fileHash })
          }
        }

        fileReader.onerror = function () {
          console.warn('oops, something went wrong.')
        }

        function loadNext () {
          const start = currentChunk * chunkSize
          const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize
          const chunk = blobSlice.call(file, start, end)
          this.fileChunkList.value.push({ chunk, size: chunk.size, name: this.currFile.value.name })
          fileReader.readAsArrayBuffer(chunk)
        }

        loadNext()
      })
    },
    uploadChunks (fileHash) {
      const requests = this.fileChunkList.value.map((item, index) => {
        const formData = new FormData()
        formData.append(`${this.currFile.value.name}-${fileHash}-${index}`, item.chunk)
        formData.append('filename', this.currFile.value.name)
        formData.append('hash', `${fileHash}-${index}`)
        formData.append('fileHash', fileHash)
        return uploadFile('/upload', formData, this.onUploadProgress(item))
      })

      Promise.all(requests).then(() => {
        mergeChunks('/mergeChunks', { size: this.DefualtChunkSize, filename: this.currFile.value.name })
      })
    },
    // 分块进度条
    onUploadProgress (item, e) {
      item.percentage = parseInt(String((e.loaded / e.total) * 100))
    }

  }
}
</script>

<style>
</style>
